﻿/*
* object.watch v0.0.1: Cross-browser object.watch
*
* By Elijah Grey, http://eligrey.com
*
* A shim that partially implements object.watch and object.unwatch
* in browsers that have accessor support.
*
* Public Domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/

//// object.watch
//  Object.prototype.mywatch = function (prop, handler)
//  {
//    var oldval = this[prop], newval = oldval,
//        getter = function ()
//        {
//          return newval;
//        },
//        setter = function (val)
//        {
//          oldval = newval;
//          if (handler != null)
//          {
//            return newval = handler(this, prop, oldval, val);
//          }
//          else
//          {
//            return val;
//          }
//        };
//    if (delete this[prop])
//    { // can't watch constants
//      if (Object.defineProperty) // ECMAScript 5
//        Object.defineProperty(this, prop, {
//          get: getter,
//          set: setter
//        });
//      else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__)
//      { // legacy
//        Object.prototype.__defineGetter__(this, prop, getter);
//        Object.prototype.__defineSetter__(this, prop, setter);
//      }
//    }
//  };

//// object.unwatch
//  Object.prototype.myunwatch = function (prop)
//  {
//    var val = this[prop];
//    delete this[prop]; // remove accessors
//    this[prop] = val;
//  };

///Part by Sergiu Jurca. Extending the Object class crashes jQuery. Below is an alternate solution.

  HackApp = new Object();
  HackApp.Watch = function (obj, prop, handler)
  {
    var oldval = obj[prop], newval = oldval,
        getter = function ()
        {
          return newval;
        },
        setter = function (val)
        {
          oldval = newval;
          if (handler != null)
          {
            return newval = handler(obj, prop, oldval, val);
          }
          else
          {
            return val;
          }
        };
    if (delete obj[prop])
    { // can't watch constants
      try
      {
        if (Object.defineProperty) // ECMAScript 5
        {
          Object.defineProperty(obj, prop, {
            get: getter,
            set: setter
          });
        }
        else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__)
        { // legacy
          Object.prototype.__defineGetter__(obj, prop, getter);
          Object.prototype.__defineSetter__(obj, prop, setter);
        }

        return true;
      }
      catch (ex)
      {
        obj[prop] = oldval;
      }
    }
    return false;
  };

  HackApp.Unwatch = function (obj, prop)
  {
    var val = obj[prop];
    delete obj[prop]; // remove accessors
    obj[prop] = val;
  };